﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using Autodesk.Revit.DB.Electrical;
using Autodesk.Revit.DB.Mechanical;
using Autodesk.Revit.DB.Plumbing;
using Autodesk.Revit.DB.Structure;
using Autodesk.Revit.UI;
using YArchitech.Revit;

namespace YJKView
{
	public partial class DlgModelView : System.Windows.Forms.Form
	{
		[DllImport("user32.dll")]
		public static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);

		public static DlgModelView GetInstance(UIApplication app)
		{
			if (DlgModelView.dmv == null || DlgModelView.dmv.IsDisposed)
			{
				DlgModelView.dmv = new DlgModelView(app);
			}
			return DlgModelView.dmv;
		}

		public DlgModelView(UIApplication uiApp)
		{
			this.revit = uiApp;
			this.doc = uiApp.ActiveUIDocument.Document;
			this.InitializeComponent();
			this.Request = new Request();
		}

		private void DlgModelView_Load(object sender, EventArgs e)
		{
			this.ReadData();
			this.ShowByCategory();
		}

		private void setChildNodeCheckedState(TreeNode currNode, bool state)
		{
			TreeNodeCollection nodes = currNode.Nodes;
			if (nodes.Count > 0)
			{
				foreach (object obj in nodes)
				{
					TreeNode treeNode = (TreeNode)obj;
					treeNode.Checked = state;
					this.setChildNodeCheckedState(treeNode, state);
				}
			}
		}

		private void setParentNodeCheckedState(TreeNode currNode, bool state)
		{
			TreeNode parent = currNode.Parent;
			parent.Checked = state;
			if (currNode.Parent.Parent != null)
			{
				this.setParentNodeCheckedState(currNode.Parent, state);
			}
		}

		[DllImport("user32.dll", EntryPoint = "SendMessageA")]
		public static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);

		private void DlgModelView_MouseLeave(object sender, EventArgs e)
		{
			if (!base.ClientRectangle.Contains(base.PointToClient(Cursor.Position)))
			{
				int wMsg = 7;
				DlgModelView.SendMessage(ShowDlgApp._hWndRevit.Handle, wMsg, IntPtr.Zero, IntPtr.Zero);
				return;
			}
			base.Focus();
		}

		private void tvByLevel_AfterSelect(object sender, TreeViewEventArgs e)
		{
		}

		private void tvByCategory_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
		{
			if (e.Node != null && e.Node.Tag is Element)
			{
				Element element = (Element)e.Node.Tag;
				Autodesk.Revit.DB.View activeView = this.revit.ActiveUIDocument.Document.ActiveView;
				if (!element.IsHidden(activeView))
				{
					RevitVersionFuncs.ClearSelection(this.revit.ActiveUIDocument.Selection);
					RevitVersionFuncs.AddToSelection(this.revit.ActiveUIDocument.Selection, element);
					this.revit.ActiveUIDocument.ShowElements(element);
				}
			}
		}

		private void tvByLevel_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
		{
			if (e.Node != null && e.Node.Tag is Element)
			{
				Element element = (Element)e.Node.Tag;
				Autodesk.Revit.DB.View activeView = this.revit.ActiveUIDocument.Document.ActiveView;
				if (!element.IsHidden(activeView))
				{
					RevitVersionFuncs.ClearSelection(this.revit.ActiveUIDocument.Selection);
					RevitVersionFuncs.AddToSelection(this.revit.ActiveUIDocument.Selection, element);
					this.revit.ActiveUIDocument.ShowElements(element);
				}
			}
		}

		public void MakeRequest(RequestId request)
		{
			this.Request.Make(request);
		}

		public void setNodeElementVisible(TreeNode tn)
		{
			if (!tn.Checked)
			{
				if (tn.Tag is Element)
				{
					this.es.Add(((Element)tn.Tag).Id);
					this.vis = false;
					this.MakeRequest(RequestId.SetVisible);
					return;
				}
				bool flag = false;
				foreach (object obj in tn.Nodes)
				{
					TreeNode treeNode = (TreeNode)obj;
					if (treeNode.Tag is Element)
					{
						this.es.Add(((Element)treeNode.Tag).Id);
						flag = true;
					}
					else
					{
						this.setNodeElementVisible(treeNode);
					}
				}
				if (flag)
				{
					this.vis = false;
					this.MakeRequest(RequestId.SetVisible);
					return;
				}
			}
			else
			{
				if (tn.Tag is Element)
				{
					this.es.Add(((Element)tn.Tag).Id);
					this.vis = true;
					this.MakeRequest(RequestId.SetVisible);
					return;
				}
				bool flag2 = false;
				foreach (object obj2 in tn.Nodes)
				{
					TreeNode treeNode2 = (TreeNode)obj2;
					if (treeNode2.Tag is Element)
					{
						flag2 = true;
						this.es.Add(((Element)treeNode2.Tag).Id);
					}
					else
					{
						this.setNodeElementVisible(treeNode2);
					}
				}
				if (flag2)
				{
					this.vis = true;
					this.MakeRequest(RequestId.SetVisible);
				}
			}
		}

		private void tvByCategory_AfterCheck(object sender, TreeViewEventArgs e)
		{
		}

		private void tvByLevel_AfterCheck(object sender, TreeViewEventArgs e)
		{
		}

		public void ShowByCategory()
		{
			Document document = this.revit.ActiveUIDocument.Document;
			this.tvByCategory.Nodes.Clear();
			Dictionary<string, Dictionary<string, List<Element>>> dictionary = new Dictionary<string, Dictionary<string, List<Element>>>();
			this.SearchDocumentByCategory(dictionary, document, typeof(FamilyInstance));
			this.SearchDocumentByCategory(dictionary, document, typeof(AnalyticalModelSurface));
			this.SearchDocumentByCategory(dictionary, document, typeof(AnalyticalModel));
			this.SearchDocumentByCategory(dictionary, document, typeof(Wall));
			this.SearchDocumentByCategory(dictionary, document, typeof(Truss));
			this.SearchDocumentByCategory(dictionary, document, typeof(Floor));
			this.SearchDocumentByCategory(dictionary, document, typeof(Opening));
			this.SearchDocumentByCategory(dictionary, document, typeof(AreaLoad));
			this.SearchDocumentByCategory(dictionary, document, typeof(LineLoad));
			this.SearchDocumentByCategory(dictionary, document, typeof(CableTray));
			this.SearchDocumentByCategory(dictionary, document, typeof(Duct));
			this.SearchDocumentByCategory(dictionary, document, typeof(FootPrintRoof));
			this.SearchDocumentByCategory(dictionary, document, typeof(Pipe));
			this.SearchDocumentByCategory(dictionary, document, typeof(Conduit));
			this.SearchDocumentByCategory(dictionary, document, typeof(Railing));
			this.SearchDocumentByCategory(dictionary, document, typeof(CeilingAndFloor));
			this.SearchDocumentByCategory(dictionary, document, RevitVersionFuncs.GetWallFoundation());
			this.SearchDocumentByCategory(dictionary, document, typeof(Ceiling));
			this.SearchDocumentByCategory(dictionary, document, typeof(BeamSystem));
            this.SearchDocumentByCategory(dictionary, document, (BuiltInCategory)(-2000120));
			this.SearchDocumentByCategory(dictionary, document, RevitVersionFuncs.GetBoundaryConditionsType());
			this.SearchDocumentByCategory(dictionary, document, typeof(ImportInstance));
			this.SearchDocumentByCategory(dictionary, document, typeof(RevitLinkInstance));
			TreeNode treeNode = new TreeNode();
			treeNode.Text = document.Title;
			treeNode.Tag = document.Title;
			treeNode.Checked = true;
			this.tvByCategory.Nodes.Add(treeNode);
			foreach (KeyValuePair<string, Dictionary<string, List<Element>>> keyValuePair in dictionary)
			{
				string key = keyValuePair.Key;
				TreeNode treeNode2 = new TreeNode();
				treeNode2.Text = key;
				treeNode2.Tag = key;
				treeNode2.Checked = true;
				treeNode.Nodes.Add(treeNode2);
				foreach (KeyValuePair<string, List<Element>> keyValuePair2 in keyValuePair.Value)
				{
					string key2 = keyValuePair2.Key;
					TreeNode treeNode3 = new TreeNode();
					treeNode3.Text = key2;
					treeNode3.Tag = key2;
					treeNode3.Checked = true;
					treeNode2.Nodes.Add(treeNode3);
					foreach (Element element in keyValuePair2.Value)
					{
						TreeNode treeNode4 = new TreeNode();
						treeNode4.Text = string.Format("{0}(id:{1})", element.Name, element.Id.ToString());
						treeNode4.Tag = element;
						Autodesk.Revit.DB.View activeView = this.revit.ActiveUIDocument.Document.ActiveView;
						treeNode4.Checked = !element.IsHidden(activeView);
						if (!treeNode4.Checked)
						{
							treeNode2.Checked = false;
							treeNode3.Checked = false;
							treeNode.Checked = false;
						}
						treeNode3.Nodes.Add(treeNode4);
					}
				}
			}
			this.tvByCategory.ExpandAll();
			foreach (object obj in this.tvByCategory.Nodes[0].Nodes)
			{
				TreeNode treeNode5 = (TreeNode)obj;
				treeNode5.Collapse();
			}
		}

		public void ShowByLevel()
		{
			this.tvByLevel.Nodes.Clear();
			Dictionary<string, Dictionary<string, List<Element>>> dictionary = new Dictionary<string, Dictionary<string, List<Element>>>();
			this.SearchDocumentByLevel(dictionary, this.doc, typeof(FamilyInstance));
			this.SearchDocumentByLevel(dictionary, this.doc, typeof(AnalyticalModelSurface));
			this.SearchDocumentByLevel(dictionary, this.doc, typeof(AnalyticalModel));
			this.SearchDocumentByLevel(dictionary, this.doc, typeof(Wall));
			this.SearchDocumentByLevel(dictionary, this.doc, typeof(Truss));
			this.SearchDocumentByLevel(dictionary, this.doc, typeof(Floor));
			this.SearchDocumentByLevel(dictionary, this.doc, typeof(Opening));
			this.SearchDocumentByLevel(dictionary, this.doc, typeof(AreaLoad));
			this.SearchDocumentByLevel(dictionary, this.doc, typeof(LineLoad));
			this.SearchDocumentByLevel(dictionary, this.doc, typeof(CableTray));
			this.SearchDocumentByLevel(dictionary, this.doc, typeof(Duct));
			this.SearchDocumentByLevel(dictionary, this.doc, typeof(FootPrintRoof));
			this.SearchDocumentByLevel(dictionary, this.doc, typeof(Railing));
			this.SearchDocumentByLevel(dictionary, this.doc, typeof(CeilingAndFloor));
			this.SearchDocumentByLevel(dictionary, this.doc, RevitVersionFuncs.GetWallFoundation());
			this.SearchDocumentByLevel(dictionary, this.doc, typeof(Ceiling));
			this.SearchDocumentByLevel(dictionary, this.doc, typeof(BeamSystem));
			this.SearchDocumentByLevel(dictionary, this.doc, RevitVersionFuncs.GetBoundaryConditionsType());
			this.SearchDocumentByCategory(dictionary, this.doc,  (BuiltInCategory)(-2000120));
			this.SearchDocumentByCategory(dictionary, this.doc, typeof(ImportInstance));
			this.SearchDocumentByCategory(dictionary, this.doc, typeof(RevitLinkInstance));
			TreeNode treeNode = new TreeNode();
			treeNode.Text = this.doc.Title;
			treeNode.Tag = this.doc.Title;
			treeNode.Checked = true;
			this.tvByLevel.Nodes.Add(treeNode);
			foreach (KeyValuePair<string, Dictionary<string, List<Element>>> keyValuePair in (from c in dictionary
			orderby c.Key descending
			select c).ToList<KeyValuePair<string, Dictionary<string, List<Element>>>>())
			{
				string key = keyValuePair.Key;
				TreeNode treeNode2 = new TreeNode();
				treeNode2.Text = key;
				treeNode2.Tag = key;
				treeNode2.Checked = true;
				treeNode.Nodes.Add(treeNode2);
				foreach (KeyValuePair<string, List<Element>> keyValuePair2 in keyValuePair.Value)
				{
					string key2 = keyValuePair2.Key;
					TreeNode treeNode3 = new TreeNode();
					treeNode3.Text = key2;
					treeNode3.Tag = key2;
					treeNode3.Checked = true;
					treeNode2.Nodes.Add(treeNode3);
					foreach (Element element in keyValuePair2.Value)
					{
						TreeNode treeNode4 = new TreeNode();
						treeNode4.Text = string.Format("{0}(id:{1})", element.Name, element.Id.ToString());
						treeNode4.Tag = element;
						Autodesk.Revit.DB.View activeView = this.revit.ActiveUIDocument.Document.ActiveView;
						treeNode4.Checked = !element.IsHidden(activeView);
						if (!treeNode4.Checked)
						{
							treeNode3.Checked = false;
							treeNode2.Checked = false;
							treeNode.Checked = false;
						}
						treeNode3.Nodes.Add(treeNode4);
					}
				}
			}
			this.tvByLevel.ExpandAll();
			foreach (object obj in this.tvByLevel.Nodes[0].Nodes)
			{
				TreeNode treeNode5 = (TreeNode)obj;
				treeNode5.Collapse();
			}
		}

		public void SearchDocumentByCategory(Dictionary<string, Dictionary<string, List<Element>>> mapCatToFam, Document myDoc, Type type)
		{
			IEnumerable<Element> familiesCollector = new FilteredElementCollector(myDoc).OfClass(type).WhereElementIsNotElementType();
			this.SearchDocumentByCategory(mapCatToFam, familiesCollector);
		}

		public void SearchDocumentByCategory(Dictionary<string, Dictionary<string, List<Element>>> mapCatToFam, Document myDoc, BuiltInCategory category)
		{
			IEnumerable<Element> familiesCollector = new FilteredElementCollector(myDoc).OfCategory(category).WhereElementIsNotElementType();
			this.SearchDocumentByCategory(mapCatToFam, familiesCollector);
		}

		public void SearchDocumentByLevel(Dictionary<string, Dictionary<string, List<Element>>> mapCatToFam, Document myDoc, Type type)
		{
			IEnumerable<Element> familiesCollector = new FilteredElementCollector(myDoc).OfClass(type).WhereElementIsNotElementType();
			this.SearchDocumentByLevel(mapCatToFam, familiesCollector);
		}

		public void SearchDocumentByLevel(Dictionary<string, Dictionary<string, List<Element>>> mapCatToFam, Document myDoc, BuiltInCategory category)
		{
			try
			{
				IEnumerable<Element> familiesCollector = new FilteredElementCollector(myDoc).OfCategory(category).WhereElementIsNotElementType();
				this.SearchDocumentByLevel(mapCatToFam, familiesCollector);
			}
			catch
			{
			}
		}

		private void SearchDocumentByLevel(Dictionary<string, Dictionary<string, List<Element>>> mapCatToFam, IEnumerable<Element> familiesCollector)
		{
			foreach (Element element in familiesCollector)
			{
				if (element.Category != null)
				{
					string key = element.Category.Name;
					if (element is ImportInstance)
					{
						key = "导入模型";
					}
					else if (element is RevitLinkInstance)
					{
						key = "Revit链接模型";
					}
					else
					{
						key = element.Category.Name;
					}
					string key2 = "其他";
					if (element.GetYJKLevel() != null)
					{
						key2 = element.GetYJKLevel().Name;
					}
					else
					{
						try
						{
							if (element.Category.Id.IntegerValue == -2000120)
							{
								key2 = this.GetStairsBottomLevel(element);
							}
							if (element.Category.Id.IntegerValue == -2001320)
							{
								try
								{
									Parameter parameter = element.GetParameter(BuiltInParameter.INSTANCE_REFERENCE_LEVEL_PARAM);
									ElementId elementId = parameter.AsElementId();
									Level level = element.Document.GetElement(elementId) as Level;
									key2 = level.Name;
								}
								catch
								{
								}
							}
							Parameter parameter2 = element.get_Parameter(BuiltInParameter.RBS_START_LEVEL_PARAM);
							if (parameter2 != null)
							{
								Level level2 = this.revit.ActiveUIDocument.Document.GetElement(parameter2.AsElementId()) as Level;
								key2 = level2.Name;
							}
						}
						catch
						{
						}
					}
					if (mapCatToFam.ContainsKey(key2))
					{
						if (mapCatToFam[key2].ContainsKey(key))
						{
							mapCatToFam[key2][key].Add(element);
						}
						else
						{
							mapCatToFam[key2].Add(key, new List<Element>
							{
								element
							});
						}
					}
					else
					{
						mapCatToFam.Add(key2, new Dictionary<string, List<Element>>
						{
							{
								key,
								new List<Element>
								{
									element
								}
							}
						});
					}
				}
			}
		}

		private void SearchDocumentByCategory(Dictionary<string, Dictionary<string, List<Element>>> mapCatToFam, IEnumerable<Element> familiesCollector)
		{
			foreach (Element element in familiesCollector)
			{
				if (element.Category != null)
				{
					string key = element.Category.Name;
					if (element is ImportInstance)
					{
						key = "导入模型";
					}
					else if (element is RevitLinkInstance)
					{
						key = "Revit链接模型";
					}
					else
					{
						key = element.Category.Name;
					}
					string key2 = "其他";
					if (element.GetYJKLevel() != null)
					{
						key2 = element.GetYJKLevel().Name;
					}
					else
					{
						try
						{
							if (element.Category.Id.IntegerValue == -2000120)
							{
								key2 = this.GetStairsBottomLevel(element);
							}
							if (element.Category.Id.IntegerValue == -2001320)
							{
								try
								{
									Parameter parameter = element.GetParameter(BuiltInParameter.INSTANCE_REFERENCE_LEVEL_PARAM);
									ElementId elementId = parameter.AsElementId();
									Level level = element.Document.GetElement(elementId) as Level;
									key2 = level.Name;
								}
								catch
								{
								}
							}
							Parameter parameter2 = element.get_Parameter(BuiltInParameter.RBS_START_LEVEL_PARAM);
							if (parameter2 != null)
							{
								Level level2 = this.revit.ActiveUIDocument.Document.GetElement(parameter2.AsElementId()) as Level;
								key2 = level2.Name;
							}
						}
						catch
						{
						}
					}
					if (mapCatToFam.ContainsKey(key))
					{
						if (mapCatToFam[key].ContainsKey(key2))
						{
							mapCatToFam[key][key2].Add(element);
						}
						else
						{
							mapCatToFam[key].Add(key2, new List<Element>
							{
								element
							});
						}
					}
					else
					{
						mapCatToFam.Add(key, new Dictionary<string, List<Element>>
						{
							{
								key2,
								new List<Element>
								{
									element
								}
							}
						});
					}
				}
			}
		}

		private string GetStairsBottomLevel(Element elem)
		{
			try
			{
				ElementId elementId = elem.GetParameter(BuiltInParameter.STAIRS_BASE_LEVEL_PARAM).AsElementId();
				if (null != elementId)
				{
					Level level = elem.Document.GetElement(elementId) as Level;
					return level.Name;
				}
			}
			catch
			{
			}
			return "未知标高";
		}

		private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
		{
			switch (this.tabControl1.SelectedIndex)
			{
			case 0:
				this.ShowByCategory();
				return;
			case 1:
				this.ShowByLevel();
				return;
			default:
				return;
			}
		}

		public Request Request
		{
			get
			{
				return this.m_request;
			}
			private set
			{
				this.m_request = value;
			}
		}

		private void SaveData()
		{
			string tempPath = Path.GetTempPath();
			string path = tempPath + "DlgModelView.dat";
			FileStream fileStream = new FileStream(path, FileMode.Create);
			StreamWriter streamWriter = new StreamWriter(fileStream);
			streamWriter.WriteLine(base.Location.X);
			streamWriter.WriteLine(base.Location.Y);
			streamWriter.Flush();
			streamWriter.Close();
			fileStream.Close();
		}

		private bool ReadData()
		{
			string tempPath = Path.GetTempPath();
			string path = tempPath + "DlgModelView.dat";
			if (!File.Exists(path))
			{
				base.StartPosition = FormStartPosition.CenterScreen;
				return true;
			}
			base.StartPosition = FormStartPosition.Manual;
			FileStream fileStream = new FileStream(path, FileMode.Open);
			StreamReader streamReader = new StreamReader(fileStream);
			streamReader.BaseStream.Seek(0L, SeekOrigin.Begin);
			int x = Convert.ToInt32(streamReader.ReadLine());
			int y = Convert.ToInt32(streamReader.ReadLine());
            base.Location = new System.Drawing.Point(x, y);
			streamReader.Close();
			fileStream.Close();
			return true;
		}

		private void DlgModelView_FormClosing(object sender, FormClosingEventArgs e)
		{
			this.SaveData();
		}

		private void tabControl1_KeyPress(object sender, KeyPressEventArgs e)
		{
			if (e.KeyChar == '\u001b')
			{
				base.Close();
			}
		}

		private void DlgModelView_KeyPress(object sender, KeyPressEventArgs e)
		{
			if (e.KeyChar == '\u001b')
			{
				base.Close();
			}
		}

		private UIApplication revit;

		private Document doc;

		public List<ElementId> es = new List<ElementId>();

		public bool vis;

		private static DlgModelView dmv;

		private Request m_request;
	}
}
